using Microsoft.Practices.Unity;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using UniAspect.UnityCommon;

namespace UniAspect.UnitTests
{
    [TestFixture]
    public class ContainerChildWithSingleton
    {
        [Test]
        public void ChildContainerOverridesSingleton()
        {
            var container = new UnityContainer();
            container.RegisterSingleton<BaseClass>();
            container.RegisterSingleton<ISomeInterface, Implementation1>();

            // creating a child seems to have no effect on sigletons!
            var child = container.CreateChildContainer();
            child.RegisterSingleton<ISomeInterface, Implementation2>();

            var mainResolution = container.Resolve<BaseClass>();
            var childResolution = child.Resolve<BaseClass>();
            Assert.That(mainResolution.Interface, Is.InstanceOfType(typeof(Implementation1)));
            Assert.That(childResolution.Interface, Is.InstanceOfType(typeof(Implementation1)));
        }

        [Test]
        public void OverrideGeneric()
        {
            var container = new UnityContainer();
            container.RegisterSingleton(typeof(IBaseInterface<>), typeof(BaseStub<>));
            container.RegisterSingleton<ISomeInterface, Implementation1>();

            // creating a child seems to have no effect on sigletons!
            var child = container.CreateChildContainer();
            child.RegisterSingleton<ISomeInterface, Implementation2>();

            var mainResolution = container.Resolve<IBaseInterface<Stub1>>();
            var childResolution = child.Resolve<IBaseInterface<Stub1>>();
            Assert.That(mainResolution.Interface, Is.InstanceOfType(typeof(Implementation1)));
            Assert.That(childResolution.Interface, Is.InstanceOfType(typeof(Implementation1)));
        }

        [Test]
        public void ManySingletons()
        {
            var container = new UnityContainer();
            container.RegisterSingleton<ISomeInterface, Implementation1>();
            container.RegisterSingleton<Implementation1>();

            var resolve1 = container.Resolve<Implementation1>();
            var resolve2 = container.Resolve<ISomeInterface>();
            Assert.That(resolve1, Is.SameAs(resolve2));
        }


        public class Stub1
        {
        }

        public class Stub2
        {
        }

        public class BaseStub<T> : IBaseInterface<T>
        {
            [Dependency]
            public ISomeInterface Interface { get; set; }

            public T DoSomething(T value)
            {
                return value;
            }
        }

        public interface IBaseInterface<T>
        {
            T DoSomething(T value);
            ISomeInterface Interface { get; }
        }

        public class BaseClass
        {
            [Dependency]
            public ISomeInterface Interface { get; set; }
        }


        public class SubClass1 : BaseClass
        {

        }

        public class SubClass2 : BaseClass
        {

        }

        public interface ISomeInterface
        {
        }

        public class Implementation1 : ISomeInterface
        {

        }

        public class Implementation2 : ISomeInterface
        {

        }
    }
}